using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using PickGold.Charting.ChartTypes;
using PickGold.Charting.Design;
using System.Drawing.Design;

namespace PickGold.Charting
{
	[DefaultProperty("Enabled"), SRDescription("DescriptionAttributeGrid_Grid"), AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	public class Grid
	{
		private Axis _axis;
		internal Color borderColor;
		internal ChartDashStyle borderDashStyle;
		internal int borderWidth;
		internal bool enabled;
		internal bool enabledChanged;
		internal double interval;
		internal bool intervalChanged;
		internal double intervalOffset;
		internal bool intervalOffsetChanged;
		internal DateTimeIntervalType intervalOffsetType;
		internal bool intervalOffsetTypeChanged;
		internal DateTimeIntervalType intervalType;
		internal bool intervalTypeChanged;
		internal bool majorGridTick;
		internal const double NumberOfDateTimeIntervals = 4.0;
		internal const double NumberOfIntervals = 5.0;

		public Grid()
		{
			this.borderColor = Color.Black;
			this.borderWidth = 1;
			this.borderDashStyle = ChartDashStyle.Solid;
			this.enabled = true;
		}

		internal Grid(Axis axis, bool major)
		{
			this.borderColor = Color.Black;
			this.borderWidth = 1;
			this.borderDashStyle = ChartDashStyle.Solid;
			this.enabled = true;
			this.Initialize(axis, major);
		}

		private void DrawGrid(ChartGraphics graph, double current)
		{
			CommonElements common = this._axis.Common;
			PointF empty = PointF.Empty;
			PointF tf2 = PointF.Empty;
			RectangleF ef = this._axis.PlotAreaPosition.ToRectangleF();
			if ((this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right))
			{
				empty.X = ef.X;
				tf2.X = ef.Right;
				empty.Y = (float)this._axis.GetLinearPosition(current);
				tf2.Y = empty.Y;
			}
			if ((this._axis.AxisPosition == AxisPosition.Top) || (this._axis.AxisPosition == AxisPosition.Bottom))
			{
				empty.Y = ef.Y;
				tf2.Y = ef.Bottom;
				empty.X = (float)this._axis.GetLinearPosition(current);
				tf2.X = empty.X;
			}
			if (common.ProcessModeRegions)
			{
				if (this._axis.ChartArea.Area3DStyle.Enable3D && !this._axis.ChartArea.chartAreaIsCurcular)
				{
					if (!common.ProcessModePaint)
					{
						graph.Draw3DGridLine(this._axis.ChartArea, this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2, (this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right), common, this);
					}
				}
				else if (!this._axis.ChartArea.chartAreaIsCurcular)
				{
					using (GraphicsPath path = new GraphicsPath())
					{
						if (Math.Abs((float)(empty.X - tf2.X)) > Math.Abs((float)(empty.Y - tf2.Y)))
						{
							path.AddLine(empty.X, empty.Y - 1f, tf2.X, tf2.Y - 1f);
							path.AddLine(tf2.X, tf2.Y + 1f, empty.X, empty.Y + 1f);
							path.CloseAllFigures();
						}
						else
						{
							path.AddLine(empty.X - 1f, empty.Y, tf2.X - 1f, tf2.Y);
							path.AddLine(tf2.X + 1f, tf2.Y, empty.X + 1f, empty.Y);
							path.CloseAllFigures();
						}
						common.HotRegionsList.AddHotRegion(path, true, ChartElementType.Gridlines, this);
					}
				}
			}
			if (common.ProcessModePaint)
			{
				if (this._axis.ChartArea.chartAreaIsCurcular)
				{
					if (this._axis.axisType == AxisName.Y)
					{
						this._axis.DrawCircularLine(this, graph, this.borderColor, this.borderWidth, this.borderDashStyle, empty.Y);
					}
					if (this._axis.axisType == AxisName.X)
					{
						ICircularChartType circularChartType = this._axis.ChartArea.GetCircularChartType();
						if ((circularChartType != null) && circularChartType.RadialGridLinesSupported())
						{
							this._axis.DrawRadialLine(this, graph, this.borderColor, this.borderWidth, this.borderDashStyle, current);
						}
					}
				}
				else if (!this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular)
				{
					graph.DrawLineRel(this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2);
				}
				else
				{
					graph.Draw3DGridLine(this._axis.ChartArea, this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2, (this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right), this._axis.Common, this);
				}
			}
		}

		internal Axis GetAxis()
		{
			return this._axis;
		}

		internal double GetInterval()
		{
			if ((this.majorGridTick && double.IsNaN(this.interval)) && (this._axis != null))
			{
				return this._axis.Interval;
			}
			return this.interval;
		}

		internal double GetIntervalOffset()
		{
			if ((this.majorGridTick && double.IsNaN(this.intervalOffset)) && (this._axis != null))
			{
				return this._axis.IntervalOffset;
			}
			return this.intervalOffset;
		}

		internal DateTimeIntervalType GetIntervalOffsetType()
		{
			if ((this.majorGridTick && (this.intervalOffsetType == DateTimeIntervalType.NotSet)) && (this._axis != null))
			{
				return this._axis.IntervalOffsetType;
			}
			return this.intervalOffsetType;
		}

		internal DateTimeIntervalType GetIntervalType()
		{
			if ((this.majorGridTick && (this.intervalType == DateTimeIntervalType.NotSet)) && (this._axis != null))
			{
				return this._axis.IntervalType;
			}
			return this.intervalType;
		}

		private double GetLogMinimum(double current, Series axisSeries)
		{
			double viewMinimum = this._axis.ViewMinimum;
			DateTimeIntervalType type = (this.GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? this.GetIntervalType() : this.GetIntervalOffsetType();
			if ((this.GetIntervalOffset() != 0.0) && (axisSeries == null))
			{
				viewMinimum += ChartHelper.GetIntervalSize(viewMinimum, this.GetIntervalOffset(), type, axisSeries, 0.0, DateTimeIntervalType.Number, true, false);
			}
			return (viewMinimum + Math.Floor((double)(current - viewMinimum)));
		}

		internal void Initialize(Axis axis, bool major)
		{
			if ((!this.enabledChanged && (this._axis == null)) && !major)
			{
				this.enabled = false;
			}
			if (this._axis == null)
			{
				TickMark mark = this as TickMark;
				if (this.interval != 0.0)
				{
					if (mark != null)
					{
						if (major)
						{
							axis.tempMajorTickMarkInterval = this.interval;
						}
						else
						{
							axis.tempMinorTickMarkInterval = this.interval;
						}
					}
					else if (major)
					{
						axis.tempMajorGridInterval = this.interval;
					}
					else
					{
						axis.tempMinorGridInterval = this.interval;
					}
				}
				if (this.intervalType != DateTimeIntervalType.Auto)
				{
					if (mark != null)
					{
						if (major)
						{
							axis.tempTickMarkIntervalType = this.intervalType;
						}
					}
					else if (major)
					{
						axis.tempGridIntervalType = this.intervalType;
					}
				}
			}
			this._axis = axis;
			this.majorGridTick = major;
		}

		internal void Invalidate()
		{
		}

		internal void Paint(ChartGraphics graph)
		{
			if (this.enabled)
			{
				if (this._axis.IsCustomGridLines())
				{
					this.PaintCustom(graph);
				}
				else
				{
					Series series = null;
					if ((this._axis.axisType == AxisName.X) || (this._axis.axisType == AxisName.X2))
					{
						List<string> xAxesSeries = this._axis.ChartArea.GetXAxesSeries((this._axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, this._axis.SubAxisName);
						if (xAxesSeries.Count > 0)
						{
							series = this._axis.Common.DataManager.Series[xAxesSeries[0]];
							if ((series != null) && !series.IsXValueIndexed)
							{
								series = null;
							}
						}
					}
					double interval = this.interval;
					DateTimeIntervalType intervalType = this.intervalType;
					double intervalOffset = this.intervalOffset;
					DateTimeIntervalType intervalOffsetType = this.intervalOffsetType;
					if (!this.majorGridTick && ((this.interval == 0.0) || double.IsNaN(this.interval)))
					{
						if (this._axis.majorGrid.GetIntervalType() == DateTimeIntervalType.Auto)
						{
							this.interval = this._axis.majorGrid.GetInterval() / 5.0;
						}
						else
						{
							DateTimeIntervalType type3 = this._axis.majorGrid.GetIntervalType();
							this.interval = this._axis.CalcInterval(this._axis.minimum, this._axis.minimum + ((this._axis.maximum - this._axis.minimum) / 4.0), true, out type3, ChartValueType.DateTime);
							this.intervalType = type3;
							this.intervalOffsetType = this._axis.majorGrid.GetIntervalOffsetType();
							this.intervalOffset = this._axis.majorGrid.GetIntervalOffset();
						}
					}
					double viewMinimum = this._axis.ViewMinimum;
					if ((!this._axis.ChartArea.chartAreaIsCurcular || (this._axis.axisType == AxisName.Y)) || (this._axis.axisType == AxisName.Y2))
					{
						viewMinimum = ChartHelper.AlignIntervalStart(viewMinimum, this.GetInterval(), this.GetIntervalType(), series, this.majorGridTick);
					}
					DateTimeIntervalType type = (this.GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? this.GetIntervalType() : this.GetIntervalOffsetType();
					if (((this.GetIntervalOffset() != 0.0) && !double.IsNaN(this.GetIntervalOffset())) && (series == null))
					{
						viewMinimum += ChartHelper.GetIntervalSize(viewMinimum, this.GetIntervalOffset(), type, series, 0.0, DateTimeIntervalType.Number, true, false);
					}
					if (((((this._axis.ViewMaximum - this._axis.ViewMinimum) / ChartHelper.GetIntervalSize(viewMinimum, this.GetInterval(), this.GetIntervalType(), series, 0.0, DateTimeIntervalType.Number, true)) <= 10000.0) && (this._axis.ViewMaximum > this._axis.ViewMinimum)) && (this.GetInterval() > 0.0))
					{
						int num5 = 0;
						int num6 = 1;
						double num7 = viewMinimum;
						decimal viewMaximum = (decimal)this._axis.ViewMaximum;
						while (((decimal)viewMinimum) <= viewMaximum)
						{
							if (this.majorGridTick || !this._axis.IsLogarithmic)
							{
								double num9 = this.GetInterval();
								double num = ChartHelper.GetIntervalSize(viewMinimum, num9, this.GetIntervalType(), series, this.GetIntervalOffset(), type, true);
								if (num == 0.0)
								{
									throw new InvalidOperationException(SR.ExceptionTickMarksIntervalIsZero);
								}
								if (((decimal)viewMinimum) >= ((decimal)this._axis.ViewMinimum))
								{
									this.DrawGrid(graph, viewMinimum);
								}
								viewMinimum += num;
							}
							else
							{
								double logMinimum = this.GetLogMinimum(viewMinimum, series);
								if (num7 != logMinimum)
								{
									num7 = logMinimum;
									num6 = 1;
								}
								double num11 = Math.Log(1.0 + (this.interval * num6), this._axis.logarithmBase);
								viewMinimum = num7;
								viewMinimum += num11;
								num6++;
								if (this.GetLogMinimum(viewMinimum, series) != logMinimum)
								{
									continue;
								}
								if (num11 == 0.0)
								{
									throw new InvalidOperationException(SR.ExceptionTickMarksIntervalIsZero);
								}
								if ((((decimal)viewMinimum) >= ((decimal)this._axis.ViewMinimum)) && (((decimal)viewMinimum) <= ((decimal)this._axis.ViewMaximum)))
								{
									this.DrawGrid(graph, viewMinimum);
								}
							}
							if (num5++ > 0x2710)
							{
								break;
							}
						}
						if (!this.majorGridTick)
						{
							this.interval = interval;
							this.intervalType = intervalType;
							this.intervalOffset = intervalOffset;
							this.intervalOffsetType = intervalOffsetType;
						}
					}
				}
			}
		}

		internal void PaintCustom(ChartGraphics graph)
		{
			CommonElements common = this._axis.Common;
			PointF empty = PointF.Empty;
			PointF tf2 = PointF.Empty;
			RectangleF ef = this._axis.PlotAreaPosition.ToRectangleF();
			foreach (CustomLabel label in this._axis.CustomLabels)
			{
				if ((label.GridTicks & GridTickTypes.Gridline) != GridTickTypes.Gridline)
				{
					continue;
				}
				double axisValue = (label.ToPosition + label.FromPosition) / 2.0;
				if ((axisValue < this._axis.ViewMinimum) || (axisValue > this._axis.ViewMaximum))
				{
					continue;
				}
				if ((this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right))
				{
					empty.X = ef.X;
					tf2.X = ef.Right;
					empty.Y = (float)this._axis.GetLinearPosition(axisValue);
					tf2.Y = empty.Y;
				}
				if ((this._axis.AxisPosition == AxisPosition.Top) || (this._axis.AxisPosition == AxisPosition.Bottom))
				{
					empty.Y = ef.Y;
					tf2.Y = ef.Bottom;
					empty.X = (float)this._axis.GetLinearPosition(axisValue);
					tf2.X = empty.X;
				}
				if (common.ProcessModeRegions)
				{
					if (!this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular)
					{
						using (GraphicsPath path = new GraphicsPath())
						{
							if (Math.Abs((float)(empty.X - tf2.X)) > Math.Abs((float)(empty.Y - tf2.Y)))
							{
								path.AddLine(empty.X, empty.Y - 1f, tf2.X, tf2.Y - 1f);
								path.AddLine(tf2.X, tf2.Y + 1f, empty.X, empty.Y + 1f);
								path.CloseAllFigures();
							}
							else
							{
								path.AddLine(empty.X - 1f, empty.Y, tf2.X - 1f, tf2.Y);
								path.AddLine(tf2.X + 1f, tf2.Y, empty.X + 1f, empty.Y);
								path.CloseAllFigures();
							}
							common.HotRegionsList.AddHotRegion(path, true, ChartElementType.Gridlines, this);
							goto Label_02E3;
						}
					}
					graph.Draw3DGridLine(this._axis.ChartArea, this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2, (this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right), common, this);
				}
			Label_02E3:
				if (common.ProcessModePaint)
				{
					if (!this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular)
					{
						graph.DrawLineRel(this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2);
						continue;
					}
					graph.Draw3DGridLine(this._axis.ChartArea, this.borderColor, this.borderWidth, this.borderDashStyle, empty, tf2, (this._axis.AxisPosition == AxisPosition.Left) || (this._axis.AxisPosition == AxisPosition.Right), this._axis.Common, this);
				}
			}
		}

		internal bool ShouldSerializeEnabled()
		{
			if (this.majorGridTick)
			{
				return !this.Enabled;
			}
			return this.Enabled;
		}

		internal bool ShouldSerializeInterval()
		{
			if (this.majorGridTick)
			{
				return !double.IsNaN(this.interval);
			}
			return (this.interval != 0.0);
		}

		internal bool ShouldSerializeIntervalOffset()
		{
			if (this.majorGridTick)
			{
				return !double.IsNaN(this.intervalOffset);
			}
			return (this.intervalOffset != 0.0);
		}

		internal bool ShouldSerializeIntervalOffsetType()
		{
			if (this.majorGridTick)
			{
				return (this.intervalOffsetType != DateTimeIntervalType.NotSet);
			}
			return (this.intervalOffsetType != DateTimeIntervalType.Auto);
		}

		internal bool ShouldSerializeIntervalType()
		{
			if (this.majorGridTick)
			{
				return (this.intervalType != DateTimeIntervalType.NotSet);
			}
			return (this.intervalType != DateTimeIntervalType.Auto);
		}

		internal Axis Axis
		{
			get
			{
				return this._axis;
			}
			set
			{
				this._axis = value;
			}
		}

		[PersistenceMode(PersistenceMode.Attribute), SRCategory("CategoryAttributeAppearance"), Bindable(true), SRDescription("DescriptionAttributeEnabled5")]
		public bool Enabled
		{
			get
			{
				return this.enabled;
			}
			set
			{
				this.enabled = value;
				this.enabledChanged = true;
				this.Invalidate();
			}
		}

		[Bindable(true), SRCategory("CategoryAttributeData"), SRDescription("DescriptionAttributeInterval6"), PersistenceMode(PersistenceMode.Attribute), TypeConverter(typeof(AxisElementIntervalValueConverter)), RefreshProperties(RefreshProperties.All)]
		public double Interval
		{
			get
			{
				return this.interval;
			}
			set
			{
				if (value < 0.0)
				{
					throw new ArgumentException(SR.ExceptionTickMarksIntervalIsNegative, "value");
				}
				this.interval = value;
				this.intervalChanged = true;
				if (((!this.majorGridTick && (value != 0.0)) && (!double.IsNaN(value) && (this._axis != null))) && ((this._axis.Chart != null) && this._axis.Chart.Serializing))
				{
					this.Enabled = true;
				}
				if (this._axis != null)
				{
					if (this is TickMark)
					{
						if (this.majorGridTick)
						{
							this._axis.tempMajorTickMarkInterval = this.interval;
						}
						else
						{
							this._axis.tempMinorTickMarkInterval = this.interval;
						}
					}
					else if (this.majorGridTick)
					{
						this._axis.tempMajorGridInterval = this.interval;
					}
					else
					{
						this._axis.tempMinorGridInterval = this.interval;
					}
				}
				this.Invalidate();
			}
		}

		[TypeConverter(typeof(AxisElementIntervalValueConverter)), Bindable(true), SRDescription("DescriptionAttributeIntervalOffset3"), SRCategory("CategoryAttributeData"), PersistenceMode(PersistenceMode.Attribute)]
		public double IntervalOffset
		{
			get
			{
				return this.intervalOffset;
			}
			set
			{
				this.intervalOffset = value;
				this.intervalOffsetChanged = true;
				this.Invalidate();
			}
		}

		[Bindable(true), SRCategory("CategoryAttributeData"), SRDescription("DescriptionAttributeIntervalOffsetType6"), RefreshProperties(RefreshProperties.All), PersistenceMode(PersistenceMode.Attribute)]
		public DateTimeIntervalType IntervalOffsetType
		{
			get
			{
				return this.intervalOffsetType;
			}
			set
			{
				this.intervalOffsetType = value;
				this.intervalOffsetTypeChanged = true;
				this.Invalidate();
			}
		}

		[PersistenceMode(PersistenceMode.Attribute), RefreshProperties(RefreshProperties.All), Bindable(true), SRDescription("DescriptionAttributeIntervalType3"), SRCategory("CategoryAttributeData")]
		public DateTimeIntervalType IntervalType
		{
			get
			{
				return this.intervalType;
			}
			set
			{
				this.intervalType = value;
				this.intervalTypeChanged = true;
				if (this._axis != null)
				{
					if (this is TickMark)
					{
						this._axis.tempTickMarkIntervalType = this.intervalType;
					}
					else
					{
						this._axis.tempGridIntervalType = this.intervalType;
					}
				}
				this.Invalidate();
			}
		}

		[SRDescription("DescriptionAttributeLineColor"), Editor(typeof(ChartColorEditor), typeof(UITypeEditor)), PersistenceMode(PersistenceMode.Attribute), DefaultValue(typeof(Color), "Black"), SRCategory("CategoryAttributeAppearance"), TypeConverter(typeof(ColorConverter)), Bindable(true)]
		public Color LineColor
		{
			get
			{
				return this.borderColor;
			}
			set
			{
				this.borderColor = value;
				this.Invalidate();
			}
		}

		[PersistenceMode(PersistenceMode.Attribute), SRCategory("CategoryAttributeAppearance"), Bindable(true), DefaultValue(5), SRDescription("DescriptionAttributeLineDashStyle")]
		public ChartDashStyle LineDashStyle
		{
			get
			{
				return this.borderDashStyle;
			}
			set
			{
				this.borderDashStyle = value;
				this.Invalidate();
			}
		}

		[Bindable(true), SRCategory("CategoryAttributeAppearance"), DefaultValue(1), SRDescription("DescriptionAttributeLineWidth"), PersistenceMode(PersistenceMode.Attribute)]
		public int LineWidth
		{
			get
			{
				return this.borderWidth;
			}
			set
			{
				this.borderWidth = value;
				this.Invalidate();
			}
		}
	}
}

